package com.sita.cfmoto.ui.view;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.sita.cfmoto.R;


public class CircularStatusView extends View {

    private final String TAG = CircularStatusView.class.getSimpleName();
    // all value here
    private final int MAX_VALUE = 100; //满分 100
    private final float mMaxValue = MAX_VALUE;
    private VIEW_STATUS mStatus = VIEW_STATUS.STATUS_READY;
    private ValueAnimator mProgressAnimator = null;
    // all Bitmap here
    private Bitmap backBitmap;
    private Bitmap runBitmap;
    private Drawable backImageResource = null;
    private Drawable progressImageResource = null;
    // all paint here
    private Paint mBackPaint;
    private Paint mRunPaint;
    private Paint mTextValuePaint;
    private Paint mTextUnitPaint;
    private Paint mTestColorPaint;
    private RectF mOval;
    // color here
    private int mBackGroundColor = Color.TRANSPARENT;
    private int mValueColor = Color.LTGRAY;
    private int mUnitColor = Color.LTGRAY;
    private float mAngle = 0f;
    private float mPreAngle = 0f;
    private float mCurValue = 0f;
    private float mPreValue = 0f;
    private float mAngleOffset = -90f;
    private float mAngleSweep = 0;
    private float mScale = 1;
    // string here
    private String mTextUnit = "分";
    // size here
    private int mTextValueSize = 200; // in pixel
    private int mTextUnitSize = 200; // in pixel
    private int margin = 0;
    private int mNewViewWidth = 0;
    private int mXOffset = 0;
    private int mYOffset = 0;
    private int mX0 = margin;
    private int mY0 = margin;
    public CircularStatusView(Context context) {
        super(context);
        init();
    }

    public CircularStatusView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initBar(context, attrs);
        init();
    }

    private void initBar(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DrawableProgressBar);

        backImageResource = typedArray.getDrawable(R.styleable.DrawableProgressBar_backImage);
        progressImageResource = typedArray.getDrawable(R.styleable.DrawableProgressBar_progressImage);
    }

    public void init() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        backBitmap = (backImageResource != null) ?
                ((BitmapDrawable) backImageResource).getBitmap() :
                BitmapFactory.decodeResource(getResources(), R.drawable.device_state_bg_2, options);
        runBitmap = (progressImageResource == null) ?
                BitmapFactory.decodeResource(getResources(), R.drawable.device_state_run_2, options) :
                ((BitmapDrawable) progressImageResource).getBitmap();

        mBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//消除锯齿
        mRunPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mTextValueSize = getResources().getDimensionPixelSize(R.dimen.device_status_text_value_size);
        mTextValuePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextValuePaint.setTextSize(mTextValueSize);
        mTextValuePaint.setTextAlign(Paint.Align.CENTER);
        mTextValuePaint.setColor(mValueColor);
        mTextValuePaint.setTypeface(Typeface.DEFAULT);

        mTextUnitSize = getResources().getDimensionPixelSize(R.dimen.device_status_text_unit_size);
        mTextUnitPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextUnitPaint.setTextSize(mTextUnitSize);
        mTextUnitPaint.setTextAlign(Paint.Align.CENTER);
        mTextUnitPaint.setColor(mUnitColor);
        mTextUnitPaint.setTypeface(Typeface.DEFAULT);

        mTestColorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTestColorPaint.setColor(Color.BLUE);
    }

    private void onDrawRunning(Canvas canvas) {

        // background
        Shader shader = new BitmapShader(runBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);//CLAMP 拉伸
        Matrix localMatrix = new Matrix();
        localMatrix.postScale(mScale, mScale);
        localMatrix.postTranslate(margin + mXOffset, margin + mYOffset);
        shader.setLocalMatrix(localMatrix);
        mBackPaint.setShader(shader);

        if (backBitmap != null) {
            RectF dst = new RectF(0, 0, mNewViewWidth, mNewViewWidth);
            dst.offset(mXOffset + margin, mYOffset + margin);
            canvas.drawBitmap(backBitmap, null, dst, mRunPaint);
        }

        // progress
        float startAngle = mAngleOffset + mAngleSweep;
        mOval = new RectF(0, 0, mNewViewWidth, mNewViewWidth);
        mOval.offset(mXOffset + margin, mYOffset + margin);
        canvas.drawArc(mOval, startAngle, mAngle, true, mBackPaint);
        canvas.save();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        int width = getWidth();
        int height = getHeight();
        mNewViewWidth = (width < height) ? width : height;
        mNewViewWidth -= margin * 2;

        mXOffset = (width - mNewViewWidth) / 2;
        mYOffset = height - mNewViewWidth; // align parent bottom
        mScale = (float) mNewViewWidth / (float) runBitmap.getWidth();

        mX0 = mXOffset;
        mY0 = mYOffset;

        onDrawRunning(canvas);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int viewWidthHeight = widthSize > heightSize ? heightSize : widthSize;
        setMeasuredDimension(viewWidthHeight, viewWidthHeight);
    }

    public void setValue(float value) {
        if (Float.compare(value, mMaxValue) > 0) {
            value = mMaxValue;
        }

        if (Float.compare(this.mCurValue, value) == 0) {
            return;
        }
        this.mPreValue = this.mCurValue;
        this.mCurValue = value;
        this.mPreAngle = this.mAngle;

//         no animator
        this.mAngle = getAngle();
        invalidate();
    }

    public void setValueAnimator(float value, long duration, OnProgressFinieshed listener) {
        if (Float.compare(value, mMaxValue) > 0) {
            value = mMaxValue;
        }

        if (Float.compare(this.mCurValue, value) == 0) {
            return;
        }
        this.mPreValue = this.mCurValue;
        this.mCurValue = value;
        this.mPreAngle = this.mAngle;


        // add animator here
        if (mProgressAnimator != null) {
            mProgressAnimator = null;
        }
        mProgressAnimator = ValueAnimator.ofFloat(mPreValue, mCurValue);
//        if ((mPreValue > mCurValue)) {
//            mProgressAnimator.setInterpolator(new DecelerateInterpolator());
//        } else {
//            mProgressAnimator.setInterpolator(new AccelerateInterpolator());
//        }
        mProgressAnimator.setInterpolator(new LinearInterpolator());
        mProgressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (Float) animation.getAnimatedValue();
                mAngle = getAngle(value);
                invalidate();
            }
        });
        mProgressAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (listener != null) {
                    listener.onCompleted();
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        mProgressAnimator.setDuration(duration);
        mProgressAnimator.start();
    }

    private float getAngle() {
        return (mCurValue / mMaxValue) * (360f - mAngleSweep);
    }

    private float getAngle(float value) {
        return (value / mMaxValue) * (360f - mAngleSweep);
    }

//    public void setValue(float value, int duration) {
//        if (Float.compare(value, mMaxValue) > 0) {
//            value = mMaxValue;
//        }
//
//        if (Float.compare(this.mCurValue, value) == 0) {
//            return;
//        }
//        this.mPreValue = this.mCurValue;
//        this.mCurValue = value;
//        this.mPreAngle = this.mAngle;
//
//        // no animator
////        this.mAngle = getAngle();
////        invalidate();
//
//        // add animator here
//        ValueAnimator animator = ValueAnimator.ofFloat(mPreValue, mCurValue);
//        if ((mPreValue > mCurValue)) {
//            animator.setInterpolator(new DecelerateInterpolator());
//        } else {
//            animator.setInterpolator(new AccelerateInterpolator());
//        }
//        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
//            public void onAnimationUpdate(ValueAnimator animation) {
//                float value = (Float) animation.getAnimatedValue();
//                mAngle = getAngle(value);
//                invalidate();
//            }
//        });
//        animator.setDuration(duration);
//        animator.start();
//    }

    private void resetData() {
        mAngle = 0f;
        mPreAngle = 0f;
        mCurValue = 0f;
        mPreValue = 0f;
    }

    private void resetAnimator() {
        if (mProgressAnimator != null) {
            mProgressAnimator.end();
            mProgressAnimator = null;
        }
    }

    public void reset() {
        resetData();
        resetAnimator();
        invalidate();
    }

    public enum VIEW_STATUS {
        STATUS_READY,
        STATUS_RUNNING,
    }

    // m/s
    public interface OnProgressFinieshed {
        void onCompleted();
    }

}